/*
 * LibraryStudyApp.java
 */

package librarystudy;

import com.db4o.*;
import com.db4o.config.Configuration;
import com.db4o.query.Predicate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jdesktop.application.Application;
import org.jdesktop.application.SingleFrameApplication;

import librarystudy.data.ATag;
import librarystudy.data.Book;

/**
 * The main class of the application.
 */
public class LibraryStudyApp extends SingleFrameApplication {
    public static ATag allTags;
    private static ObjectContainer db;

    public static void openDatabase() {
        db = Db4o.openFile("libraryStudy.db");
    }

    public static void dumpAllBooks() {
        db = Db4o.openFile("libraryStudy.db");

        try {
            List<Book> results = db.query(new Predicate<Book>() {
                public boolean match(Book book) {
                    return true; // all books match
                }
            });

            Iterator i = results.iterator();
            while (i.hasNext()) {
                System.out.println(i.next().toString());
                }
        } finally {
            db.close();
        }

    }

    public static void dumpAllTags() {
        Configuration config = Db4o.newConfiguration();
        config.activationDepth(10);
        db = Db4o.openFile(config, "libraryStudy.db");

        try {
            List<ATag> results = db.query(new Predicate<ATag>() {
                public boolean match(ATag book) {
                    return true; // all books match
                }
            });

            Iterator i = results.iterator();
            while (i.hasNext()) {
                System.out.println(i.next().toString());
            }
        } finally {
            db.close();
        }

    }

    public static void addBook(Book b) {
        Configuration config = Db4o.newConfiguration();
        // Recurse through the objects up an extra level
        config.updateDepth(10);
        db = Db4o.openFile(config, "libraryStudy.db");

        try {
            // Prevent multiple saves (duplicates)
            List<Book> previouslySaved = db.queryByExample(b);

            if (previouslySaved.size() > 0) {
                System.out.println("Not saving due to duplication.");
                return;
            }

            db.store(b);

            // Update the set of all tags
            ArrayList<String> arr = b.getTags();
            for (int i=0; i < arr.size(); i++) {
                final String tag = arr.get(i);
                // First check if this tag already exists
                List<ATag> results = db.query(new Predicate<ATag>() {
                    public boolean match(ATag atag) {
                        return (atag.getTagName().toUpperCase().indexOf(tag.toUpperCase()) > -1);
                    }
                });

                if (results.size() > 0) {
                    System.out.println("We have results! " + results.size()  + tag + b.getTitle());

                    // There should only be one tag, so only update that one
                    ATag updateTag = results.get(0);
                    updateTag.addTitle(b.getTitle());
                    db.store(updateTag);
                } else {
                    System.out.println("We have something new. " + tag + b.getTitle());
                    ATag newTag = new ATag(tag, b.getTitle());
                    db.store(newTag);
                }
            }

        } finally {
            db.close();
        }

    }

    public static List<Book> findAuthorAsYouType(final String author) {
        if ("".equals(author))
            return new ArrayList(); // empty list

        db = Db4o.openFile("libraryStudy.db");
        System.out.println("Author: " + author);
        try {
            List<Book> results = db.query(new Predicate<Book>() {
                public boolean match(Book book) {
                    return (book.getAuthorFormattedName().toUpperCase().indexOf(author.toUpperCase()) > -1);
                }
            });

            if (results.size() > 0) {
                System.out.println("We have results! " + results.size());
            }

            return new ArrayList(results);
        } finally {
            db.close();
        }
    }

    public static List<Book> findTitleAsYouType(final String bookName) {
        if ("".equals(bookName))
            return new ArrayList(); // empty list

        db = Db4o.openFile("libraryStudy.db");
        System.out.println("Book name: " + bookName);
        try {
            List<Book> results = db.query(new Predicate<Book>() {
                public boolean match(Book book) {
                    return (book.getTitle().toUpperCase().indexOf(bookName.toUpperCase()) > -1);
                }
            });

            if (results.size() > 0) {
                System.out.println("We have results! " + results.size());
            }

            return new ArrayList(results);
        } finally {
            db.close();
        }
    }

    public static List<ATag> findTagAsYouType(final String tag) {
        if ("".equals(tag))
            return new ArrayList(); // empty list

        db = Db4o.openFile("libraryStudy.db");
        System.out.println("Tag name: " + tag);
        try {
            List<ATag> results = db.query(new Predicate<ATag>() {
                public boolean match(ATag atag) {
                    return (atag.getTagName().toUpperCase().indexOf(tag.toUpperCase()) > -1);
                }
            });

            if (results.size() > 0) {
                System.out.println("We have results! " + results.size());
            }

            return new ArrayList(results);
        } finally {
            db.close();
        }
    }

    

    public static void closeDatabase() {
        if (db != null) {
            db.close();
            db = null;
        }
    }


    /**
     * At startup create and show the main frame of the application.
     */
    @Override protected void startup() {
        show(new LibraryStudyView(this));
    }

    /**
     * This method is to initialize the specified window by injecting resources.
     * Windows shown in our application come fully initialized from the GUI
     * builder, so this additional configuration is not needed.
     */
    @Override protected void configureWindow(java.awt.Window root) {
    }

    /**
     * A convenient static getter for the application instance.
     * @return the instance of LibraryStudyApp
     */
    public static LibraryStudyApp getApplication() {
        return Application.getInstance(LibraryStudyApp.class);
    }

    /**
     * Main method launching the application.
     */
    public static void main(String[] args) {
        System.setProperty("sun.awt.exception.handler", ExceptionDetailsHandler.class.getName());
        
        launch(LibraryStudyApp.class, args);

        dumpAllTags();
    }
}
